import * as vscode from 'vscode';
import * as fs from 'fs';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as xml2js from 'xml2js';

// 使用fs.promises代替fsPromises
const fsPromises = fs.promises;

/**
 * 获取行的缩进级别
 */
export function getIndentationLevel(line: string): number {
    // 计算行的缩进级别，基于前导空格、|、+、\等字符
    let level = 0;
    let i = 0;
    
    // 跳过前导空格
    while (i < line.length && (line[i] === ' ' || line[i] === '\t')) {
        i++;
    }
    
    // 计算缩进级别，每个 |、+ 或 \ 表示一级缩进
    while (i < line.length) {
        if (line[i] === '|' || line[i] === '+' || line[i] === '\\') {
            level++;
            i++;
            // 跳过连字符和空格
            while (i < line.length && (line[i] === '-' || line[i] === ' ' || line[i] === '\t')) {
                i++;
            }
        } else {
            break;
        }
    }
    
    return level;
}

/**
 * 判断行是否为一级依赖
 */
export function isDirectDependency(line: string, indent: number): boolean {
    // 一级依赖通常是缩进最小的依赖
    return indent === 0 || indent === 1;
}

/**
 * 添加排除传递依赖的函数
 * 改进的findDirectDepsImporting函数实现，更准确地识别传递依赖的父依赖
 */
export function findDirectDepsImporting(
    dependencyTree: string,
    targetGroupId: string,
    targetArtifactId: string,
    pomContent: string
): Array<{ groupId: string; artifactId: string }> {
    const result: Array<{ groupId: string; artifactId: string }> = [];
    const targetDep = `${targetGroupId}:${targetArtifactId}`;
    console.log(`查找引入 ${targetDep} 的一级依赖...`);

    // 标准化依赖树输出（处理不同操作系统的行尾）
    const normalizedTree = dependencyTree.replace(/\r\n/g, '\n');
    const lines = normalizedTree.split('\n');

    // 提取pom.xml中的一级依赖
    const directDepsInPom = extractDirectDependenciesFromPom(pomContent);
    console.log(`从pom.xml中提取到 ${directDepsInPom.length} 个一级依赖`);

    // 找到所有包含目标依赖的行
    const targetLines: number[] = [];
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        // 确保匹配完整的依赖标识符，避免部分匹配
        const targetDepPattern = new RegExp(`[+\\\\|][-\\\\|]\\s+${targetGroupId}:${targetArtifactId}:[^:]+:[^:]+`);
        if (targetDepPattern.test(line)) {
            targetLines.push(i);
            console.log(`在行 ${i + 1} 找到目标依赖: ${line.trim()}`);
        }
    }

    // 对于每个目标依赖出现位置，向上追溯找到一级依赖
    for (const lineIndex of targetLines) {
        const targetIndent = getIndentationLevel(lines[lineIndex]);

        // 如果目标依赖本身是一级依赖，跳过(不应该对自己添加排除)
        if (targetIndent <= 1) {
            console.log(`跳过行 ${lineIndex + 1}，目标依赖本身是一级依赖`);
            continue;
        }

        // 向上查找，直到找到一级依赖
        let currentIndent = targetIndent;
        let directDep: { groupId: string; artifactId: string } | null = null;

        for (let i = lineIndex - 1; i >= 0; i--) {
            const line = lines[i];
            const indent = getIndentationLevel(line);

            // 如果缩进更小，可能是上层依赖
            if (indent < currentIndent) {
                const depInfo = extractDependencyInfo(line);

                if (depInfo) {
                    // 如果是一级依赖
                    if (indent <= 1) {
                        const { groupId, artifactId } = depInfo;

                        // 排除目标依赖自身
                        if (groupId === targetGroupId && artifactId === targetArtifactId) {
                            console.log(`跳过目标依赖自身: ${groupId}:${artifactId}`);
                            continue;
                        }

                        // 仅当该依赖在pom.xml的一级依赖列表中时才认为是一级依赖
                        const isDirectInPom = directDepsInPom.some(
                            (dep) => dep.groupId === groupId && dep.artifactId === artifactId
                        );
                        if (!isDirectInPom) {
                            console.log(`跳过非pom.xml一级依赖: ${groupId}:${artifactId}`);
                            continue;
                        }

                        directDep = { groupId, artifactId };
                        console.log(`找到目标依赖的一级父依赖: ${groupId}:${artifactId}`);
                        break;
                    }
                }
                currentIndent = indent;
            }
        }

        // 如果找到了一级父依赖，添加到结果中(避免重复)
        if (directDep && !result.some((d) => d.groupId === directDep!.groupId && d.artifactId === directDep!.artifactId)) {
            result.push(directDep);
        }
    }

    console.log(`找到 ${result.length} 个包含目标传递依赖的一级依赖`);
    return result;
}

/**
 * 从行中提取依赖信息
 */
function extractDependencyInfo(line: string): { groupId: string, artifactId: string } | null {
    // 尝试多种格式的依赖行匹配
    // 格式1: [+\\|]--? groupId:artifactId:...
    let match = line.match(/[+\\|]\s*-+\s*([\w\.-]+):([\w\.-]+)/);
    if (match) {
        return { groupId: match[1], artifactId: match[2] };
    }
    
    // 格式2: groupId:artifactId:...
    match = line.match(/\s*([\w\.-]+):([\w\.-]+):/);
    if (match) {
        return { groupId: match[1], artifactId: match[2] };
    }
    
    // 格式3: [+\\|] groupId:artifactId:...
    match = line.match(/[+\\|]\s*([\w\.-]+):([\w\.-]+)/);
    if (match) {
        return { groupId: match[1], artifactId: match[2] };
    }
    
    return null;
}

/**
 * 分析依赖是否为一级依赖及其父依赖
 */
export function analyzeDependencyNature(dependencyTree: string, groupId: string, artifactId: string): { 
    isDirectDependency: boolean; 
    parentDependencies: Array<{groupId: string, artifactId: string}> 
} {
    // 标准化依赖树输出（处理不同操作系统的行尾）
    const normalizedTree = dependencyTree.replace(/\r\n/g, '\n');
    const lines = normalizedTree.split('\n');

    // 检查是否为一级依赖
    let isDirectDep = false;
    // 寻找是否有如下格式的依赖: "com.example:my-project:jar:1.0.0"
    const directDepPattern = new RegExp(`[+\\\\|]--\\s+${groupId}:${artifactId}:.*`, 'i');
    
    for (const line of lines) {
        if (directDepPattern.test(line) && getIndentationLevel(line) <= 1) {
            isDirectDep = true;
            break;
        }
    }

    return {
        isDirectDependency: isDirectDep,
        parentDependencies: []
    };
}

export function analyzeDependencyInPom(
    dependencyTree: string,
    groupId: string,
    artifactId: string,
    pomContent: string
): { isDirectDependency: boolean; parentDependencies: Array<{ groupId: string; artifactId: string }> } {
    // 判断是否为一级依赖
    const isDirectDep = isDirectDependencyInPom(pomContent, groupId, artifactId);

    // 查找包含此依赖的所有一级依赖
    const parentDeps = findDirectDepsImporting(dependencyTree, groupId, artifactId, pomContent);

    return {
        isDirectDependency: isDirectDep,
        parentDependencies: parentDeps
    };
}

/**
 * 注释掉一级依赖 - 更精确的方法，确保注释标签放在正确位置
 */
export async function commentOutDirectDependency(pomContent: string, groupId: string, artifactId: string): Promise<string> {
    console.log(`尝试注释依赖: ${groupId}:${artifactId}`);
    
    // 使用简单匹配方式逐步定位依赖，而不是复杂的正则表达式
    const lines = pomContent.split('\n');
    let inDependency = false;
    let startLine = -1;
    let endLine = -1;
    let foundGroupId = false;
    let foundArtifactId = false;
    
    // 第一步：逐行查找依赖
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        const trimmedLine = line.trim();
        
        // 查找依赖开始标记
        if (trimmedLine.includes('<dependency>')) {
            inDependency = true;
            startLine = i;
            foundGroupId = false;
            foundArtifactId = false;
            continue;
        }
        
        // 如果在依赖块内
        if (inDependency) {
            // 检查groupId匹配
            if (trimmedLine.includes(`<groupId>${groupId}</groupId>`)) {
                foundGroupId = true;
            }
            
            // 检查artifactId匹配
            if (trimmedLine.includes(`<artifactId>${artifactId}</artifactId>`)) {
                foundArtifactId = true;
            }
            
            // 查找依赖结束标记
            if (trimmedLine.includes('</dependency>')) {
                endLine = i;
                inDependency = false;
                
                // 如果找到匹配的依赖，退出循环
                if (foundGroupId && foundArtifactId) {
                    break;
                }
                
                // 重置标记，继续查找下一个依赖
                startLine = -1;
                endLine = -1;
            }
        }
    }
    
    // 如果找到匹配的依赖
    if (startLine >= 0 && endLine >= 0 && foundGroupId && foundArtifactId) {
        console.log(`找到匹配的依赖，行范围: ${startLine+1} 到 ${endLine+1}`);
        
        // 检查依赖是否已经被注释
        const startLineContent = lines[startLine];
        if (startLineContent.indexOf('<!--') >= 0 || 
            (startLine > 0 && lines[startLine-1].indexOf('<!--') >= 0)) {
            console.log('依赖已经被注释');
            return pomContent;
        }
        
        // 保存原始的缩进和<dependency>标签的位置
        const dependencyTagIndex = startLineContent.indexOf('<dependency>');
        const indentation = startLineContent.substring(0, dependencyTagIndex);
        const endLineContent = lines[endLine];
        const endTagIndex = endLineContent.indexOf('</dependency>') + '</dependency>'.length;
        
        // 应用注释 - 确保注释标记直接放在<dependency>标签前面和</dependency>标签后面
        lines[startLine] = startLineContent.substring(0, dependencyTagIndex) + 
                          '<!-- ' + startLineContent.substring(dependencyTagIndex);
        
        lines[endLine] = endLineContent.substring(0, endTagIndex) + 
                        ' -->' + endLineContent.substring(endTagIndex);
        
        console.log(`成功注释依赖，插入注释标记: 行 ${startLine+1} 和 行 ${endLine+1}`);
        
        return lines.join('\n');
    }
    
    console.warn(`未找到匹配的依赖: ${groupId}:${artifactId}`);
    return pomContent;
}

/**
 * 从POM文件内容中提取直接依赖
 */
export function extractDirectDependenciesFromPom(pomContent: string): Array<{groupId: string, artifactId: string}> {
    const directDeps: Array<{groupId: string, artifactId: string}> = [];
    
    try {
        // 先获取整个dependencies块
        const dependenciesMatch = pomContent.match(/<dependencies>([\s\S]*?)<\/dependencies>/);
        if (!dependenciesMatch || !dependenciesMatch[1]) {
            console.log('未找到dependencies节点');
            return directDeps;
        }
        
        const dependenciesBlock = dependenciesMatch[1];
        
        // 使用更简单的方法逐个匹配dependency块
        const dependencyBlocks = dependenciesBlock.match(/<dependency>[\s\S]*?<\/dependency>/g) || [];
        
        for (const depBlock of dependencyBlocks) {
            // 检查依赖块是否被注释
            if (depBlock.includes('<!--') && depBlock.includes('-->')) {
                continue;
            }
            
            // 提取groupId和artifactId
            const groupIdMatch = depBlock.match(/<groupId>(.*?)<\/groupId>/);
            const artifactIdMatch = depBlock.match(/<artifactId>(.*?)<\/artifactId>/);
            
            if (groupIdMatch && groupIdMatch[1] && artifactIdMatch && artifactIdMatch[1]) {
                directDeps.push({
                    groupId: groupIdMatch[1].trim(),
                    artifactId: artifactIdMatch[1].trim()
                });
            }
        }
        
        console.log(`从POM文件中提取到 ${directDeps.length} 个一级依赖`);
    } catch (error) {
        console.error('提取一级依赖时出错:', error);
    }
    
    return directDeps;
}

/**
 * 直接从POM文件内容判断是否为一级依赖
 * @param pomContent POM文件内容
 * @param groupId 依赖的groupId
 * @param artifactId 依赖的artifactId
 * @returns 是否为一级依赖
 */
export function isDirectDependencyInPom(pomContent: string, groupId: string, artifactId: string): boolean {
    try {
        console.log(`正在检查 ${groupId}:${artifactId} 是否为一级依赖...`);
        
        // 先尝试最简单的搜索，看看是否存在这个依赖的声明
        const simpleGroupIdPattern = `<groupId>\\s*${escapeRegExp(groupId)}\\s*</groupId>`;
        const simpleArtifactIdPattern = `<artifactId>\\s*${escapeRegExp(artifactId)}\\s*</artifactId>`;
        
        const hasGroupId = new RegExp(simpleGroupIdPattern, 'i').test(pomContent);
        const hasArtifactId = new RegExp(simpleArtifactIdPattern, 'i').test(pomContent);
        
        if (!hasGroupId || !hasArtifactId) {
            console.log(`在POM中未找到 ${groupId}:${artifactId} 的声明`);
            return false;
        }
        
        // 使用改进的正则表达式，更宽松地匹配依赖声明
        // 1. 先检查是否在一个非注释的dependency标签中
        // 2. 然后检查这个dependency中是否包含目标的groupId和artifactId
        
        // 使用负向前瞻确保不在注释中
        const nonCommentedDependencyPattern = 
            `(?:(?!<!--)<dependency>)[\\s\\S]*?<groupId>\\s*${escapeRegExp(groupId)}\\s*</groupId>[\\s\\S]*?<artifactId>\\s*${escapeRegExp(artifactId)}\\s*</artifactId>[\\s\\S]*?</dependency>`;
        
        const isNonCommentedDep = new RegExp(nonCommentedDependencyPattern, 'i').test(pomContent);
        console.log(`依赖 ${groupId}:${artifactId} ${isNonCommentedDep ? '找到非注释的依赖声明' : '未找到有效的依赖声明'}`);
        
        // 检查是否已被注释
        const commentedDependencyPattern = 
            `<!--[\\s\\S]*?<dependency>[\\s\\S]*?<groupId>\\s*${escapeRegExp(groupId)}</groupId>[\\s\\S]*?<artifactId>\\s*${escapeRegExp(artifactId)}</artifactId>[\\s\\S]*?</dependency>[\\s\\S]*?-->`;
        
        const isCommentedDep = new RegExp(commentedDependencyPattern, 'i').test(pomContent);
        
        if (isCommentedDep) {
            console.log(`依赖 ${groupId}:${artifactId} 已被注释`);
            return false;
        }
        
        return isNonCommentedDep;
    } catch (error) {
        console.error('检查依赖类型时出错:', error);
        // 出错时使用更宽松的判断方式，尝试处理为一级依赖
        return true;
    }
}

/**
 * 让用户选择需要添加排除项的一级依赖
 */
export async function selectDirectDependencies(
    directDeps: Array<{groupId: string, artifactId: string}>,
    targetGroupId: string,
    targetArtifactId: string
): Promise<Array<{groupId: string, artifactId: string}> | undefined> {
    interface DependencyQuickPickItem extends vscode.QuickPickItem {
        dependency: {groupId: string, artifactId: string};
    }
    
    // 创建QuickPick选项
    const quickPickItems: DependencyQuickPickItem[] = directDeps.map(dep => ({
        label: `${dep.groupId}:${dep.artifactId}`,
        picked: true, // 默认全选
        description: '一级依赖',
        dependency: dep
    }));
    
    // 显示选择界面
    const selectedItems = await vscode.window.showQuickPick(quickPickItems, {
        canPickMany: true,
        placeHolder: `选择需要添加排除 ${targetGroupId}:${targetArtifactId} 的一级依赖`,
        title: `在一级依赖中排除传递依赖`
    });
    
    if (!selectedItems || selectedItems.length === 0) {
        return undefined;
    }
    
    // 返回选中的依赖
    return selectedItems.map(item => item.dependency);
}

/**
 * 为指定依赖添加排除配置 - 使用XML解析器实现
 */
export async function addExclusionToDependency(
    pomContent: string,
    depGroupId: string,
    depArtifactId: string,
    excludeGroupId: string,
    excludeArtifactId: string
): Promise<string> {
    try {
        console.log(`为依赖 ${depGroupId}:${depArtifactId} 添加排除 ${excludeGroupId}:${excludeArtifactId}`);
        
        // 使用正则表达式查找依赖声明 - 使用更宽松的模式匹配
        const depPattern = new RegExp(
            `<dependency[^>]*>[\\s\\S]*?<groupId[^>]*>\\s*${escapeRegExp(depGroupId)}\\s*</groupId>[\\s\\S]*?<artifactId[^>]*>\\s*${escapeRegExp(depArtifactId)}\\s*</artifactId>[\\s\\S]*?</dependency>`,
            'gi'
        );
        
        let match;
        let modified = false;
        let result = pomContent;
        
        // 查找所有匹配的依赖块
        while ((match = depPattern.exec(pomContent)) !== null) {
            const depBlock = match[0];
            console.log(`找到依赖块，长度: ${depBlock.length}`);
            
            // 检查是否已包含相同的排除项
            const existingExclusionPattern = new RegExp(
                `<exclusion[^>]*>[\\s\\S]*?<groupId[^>]*>\\s*${escapeRegExp(excludeGroupId)}\\s*</groupId>[\\s\\S]*?<artifactId[^>]*>\\s*${escapeRegExp(excludeArtifactId)}\\s*</artifactId>[\\s\\S]*?</exclusion>`,
                'i'
            );
            
            if (existingExclusionPattern.test(depBlock)) {
                console.log(`依赖 ${depGroupId}:${depArtifactId} 已包含对 ${excludeGroupId}:${excludeArtifactId} 的排除项`);
                continue;
            }
            
            let newDepBlock = depBlock;
            
            // 确定缩进
            const lines = depBlock.split('\n');
            let indentation = '';
            for (const line of lines) {
                const match = line.match(/^(\s+)</);
                if (match) {
                    indentation = match[1];
                    break;
                }
            }
            
            // 如果没有找到缩进，使用默认值
            if (!indentation) {
                indentation = '    ';
            }
            
            // 检查是否已有exclusions标签
            if (/<exclusions[^>]*>[\s\S]*?<\/exclusions>/i.test(depBlock)) {
                // 已有exclusions标签，在</exclusions>前添加新exclusion
                const exclusionsEndIndex = newDepBlock.lastIndexOf('</exclusions>');
                
                const exclusionXml = `${indentation}  <exclusion>\n${indentation}    <groupId>${excludeGroupId}</groupId>\n${indentation}    <artifactId>${excludeArtifactId}</artifactId>\n${indentation}  </exclusion>\n`;
                
                newDepBlock = 
                    newDepBlock.substring(0, exclusionsEndIndex) + 
                    exclusionXml +
                    newDepBlock.substring(exclusionsEndIndex);
            } else {
                // 没有exclusions标签，在</dependency>前添加完整的exclusions
                const depEndIndex = newDepBlock.lastIndexOf('</dependency>');
                
                const exclusionsXml = `\n${indentation}  <exclusions>\n${indentation}    <exclusion>\n${indentation}      <groupId>${excludeGroupId}</groupId>\n${indentation}      <artifactId>${excludeArtifactId}</artifactId>\n${indentation}    </exclusion>\n${indentation}  </exclusions>`;
                
                newDepBlock = 
                    newDepBlock.substring(0, depEndIndex) + 
                    exclusionsXml +
                    newDepBlock.substring(depEndIndex);
            }
            
            // 替换原依赖块
            result = result.replace(depBlock, newDepBlock);
            modified = true;
            console.log(`已更新依赖块，添加了排除配置`);
        }
        
        return modified ? result : pomContent;
    } catch (error) {
        console.error(`为依赖添加排除项时出错:`, error);
        return pomContent;
    }
}

/**
 * 为多个一级依赖添加对同一传递依赖的排除项
 */
export async function addExclusionsToDirectDeps(
    pomPath: string,
    directDeps: Array<{groupId: string, artifactId: string}>,
    excludeGroupId: string,
    excludeArtifactId: string
): Promise<number> {
    try {
        // 读取POM文件内容
        let pomContent = await fsPromises.readFile(pomPath, 'utf8');
        let exclusionsAdded = 0;
        
        // 为每个一级依赖添加排除项
        for (const dep of directDeps) {
            console.log(`正在为一级依赖 ${dep.groupId}:${dep.artifactId} 添加排除项 ${excludeGroupId}:${excludeArtifactId}`);
            
            // 重要修改：等待异步函数完成，确保正确处理XML
            const updatedContent = await addExclusionToDependency(
                pomContent,
                dep.groupId,
                dep.artifactId,
                excludeGroupId,
                excludeArtifactId
            );
            
            // 检查是否实际添加了排除项
            if (updatedContent !== pomContent) {
                pomContent = updatedContent;
                exclusionsAdded++;
                console.log(`成功为 ${dep.groupId}:${dep.artifactId} 添加排除项`);
            } else {
                console.log(`为 ${dep.groupId}:${dep.artifactId} 添加排除项失败，可能已存在或依赖不存在`);
            }
        }
        
        // 只有当实际添加了排除项时，才写入文件
        if (exclusionsAdded > 0) {
            console.log(`写入更新后的POM文件...`);
            
            // 为调试目的，输出一小部分内容
            const previewLength = 300;
            const contentPreview = pomContent.length > previewLength 
                ? pomContent.substring(0, previewLength) + '...'
                : pomContent;
            console.log(`文件内容预览: ${contentPreview}`);
            
            await fsPromises.writeFile(pomPath, pomContent, 'utf8');
            console.log(`成功保存修改后的POM文件`);
        }
        
        return exclusionsAdded;
    } catch (error) {
        console.error(`添加排除项时出错:`, error);
        return 0;
    }
}

/**
 * 转义正则表达式特殊字符
 */
function escapeRegExp(string: string): string {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
